package com.luxsoft.siipap.em.replica.importadores.dbf.cxc;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;
import org.springframework.util.Assert;

import com.luxsoft.siipap.cxc.model.OrigenDeOperacion;
import com.luxsoft.siipap.cxc.rules.RevisionDeCargosRules;
import com.luxsoft.siipap.em.replica.importadores.ImportadorSupport;
import com.luxsoft.siipap.em.replica.importadores.dbf.DBFRowFilter;
import com.luxsoft.siipap.em.replica.importadores.dbf.DBFRowMapper;
import com.luxsoft.siipap.model.Sucursal;
import com.luxsoft.siipap.model.core.Cliente;
import com.luxsoft.siipap.service.ServiceLocator2;
import com.luxsoft.siipap.util.DateUtil;
import com.luxsoft.siipap.util.ValidationUtils;
import com.luxsoft.siipap.ventas.model.Cobrador;
import com.luxsoft.siipap.ventas.model.Vendedor;
import com.luxsoft.siipap.ventas.model.Venta;
import com.luxsoft.siipap.ventas.model.VentaCredito;

public class CreditoDBFMapper implements DBFRowMapper,DBFRowFilter{
	
	private Date fecha;
	
	private String prefix="MCR";
	
	private Logger logger=Logger.getLogger(getClass());
	
	public Date getFecha() {
		return DateUtil.truncate(fecha, Calendar.DATE);
	}

	public void setFecha(Date fecha) {
		this.fecha = fecha;
	}

	/*
	 * (non-Javadoc)
	 * @see com.luxsoft.siipap.em.replica.importadores.dbf.DBFRowFilter#incluir(java.util.Map)
	 */
	public boolean incluir(Map<String, Object> row) {
		
		double res=getSafaDouble(row, prefix+"IDENOPE");
		boolean ok=(res==1.0);
		if(ok){
			Date fo=(Date)row.get(prefix+"FECHA");
			return DateUtils.isSameDay(fecha, fo); 
		}
		return false;
		
		
	}

	/**
	 * Genera una venta de credito a partir de la informacion de un registro del 
	 * DBF MOVCREXX.DBF
	 * 
	 */
	public Object map(Map<String, Object> row) throws Exception {
		
		//System.out.println(row);
		
		final long numero=getSafaLong(row, prefix+"NUMDOCT");
		//System.out.println("Mapeando factura: "+numero);
		
		final int sucur=getSafaInt(row, prefix+"SUCURSA");
		final String tipo=(String)row.get(prefix+"TIPOFAC");
		final Date fecha=(Date)row.get(prefix+"FECHA");
		
		final String clave=(String)row.get(prefix+"CLAVCLI");
		final String nombre=(String)row.get(prefix+"NOMBCLI");
		String comentario=(String)row.get(prefix+"COMFAC");		
		if(!StringUtils.isBlank(comentario))
			comentario=comentario.trim();
		final int numeroFiscal=getSafaInt(row, prefix+"NOFISCA");
		final String facturista=(String)row.get(prefix+"FACTURI");
		final double importeBruto=getSafaDouble(row, prefix+"IMPARTI");
		final double subtotal=getSafaDouble(row, prefix+"SUBTOT");
		final double impuesto=getSafaDouble(row, prefix+"IMPUEST");
		final double total=getSafaDouble(row, prefix+"TOTAL");		
		final double cortes=getSafaDouble(row, prefix+"IMPCORT");
		final double manio=getSafaDouble(row, prefix+"IMPCONC");
		final double cargos=cortes+manio;
		final String surtio=(String)row.get(prefix+"SURTIO");
		final int cobrador=getSafaInt(row, prefix+"COBRADO");
		final int vendedor=getSafaInt(row, prefix+"VENDEDO");
		
		//Calculamos el descuento general
		double descuento=0;
		if(importeBruto!=0){
			try{
				double val=subtotal-cortes-manio;
				descuento=(val/importeBruto);
				if(Math.round(descuento)==1)
					descuento=0;
				else
					descuento*=100;
			}catch (Exception e) {}
		}
		
		
		String msg=MessageFormat.format("Cliente:{0} CXPFactura:{1} Sucursal{2} Serie{3} Tipo:{4} Fecha:{5,date,long}"	,clave,numero,sucur,"E",tipo,fecha);
		Assert.isTrue(numero!=0,"El numero de factura no es correcto: "+msg);
		
		Cliente c=ServiceLocator2.getClienteManager().buscarPorClave(clave);
		if(c==null){			
			c=ServiceLocator2.getClienteManager().save(new Cliente(clave,nombre));
		}
		Venta fac=new Venta();
		fac.setOrigen(OrigenDeOperacion.CRE);
		fac.setDocumento(numero);
		fac.setSerieSiipap("E");
		fac.setTipoSiipap(tipo);
		fac.setCliente(c);		
		fac.setComentario(comentario);
		Sucursal suc=ImportadorSupport.getInstance().buscarSucursal(sucur);
		fac.setSucursal(suc);
		fac.setFecha(fecha);
		fac.setNumeroFiscal(numeroFiscal);
		fac.setImporte(BigDecimal.valueOf(subtotal));		
		fac.setImpuesto(BigDecimal.valueOf(impuesto));
		fac.setTotal(BigDecimal.valueOf(total));
		fac.setSaldo(fac.getTotal());
		fac.getLog().setUpdateUser(facturista);
		fac.setSurtidor(surtio);
		fac.setDescuentoGeneral(descuento);
			//Procesar credito
		VentaCredito credito=new VentaCredito();
		credito.setVenta(fac);
		fac.setCredito(credito);	
		boolean val=ValidationUtils.isValid(credito);
			if(!val){
				ValidationUtils.debugValidation(credito);
				Assert.isTrue(val,"No es correcta la informacion para credito");
		}
		if(tipo.equals("N")|| tipo.equals("P")||tipo.equals("X")){
			fac.setPrecioBruto(false);
		}		
		fac.setCargos(BigDecimal.valueOf(cargos));
		if(fac.getCargos()!=null){
			if(fac.getCargos().doubleValue()>0){
				fac.setDescCargo("CORTES-MO");
			}else
				fac.setDescCargo(null);
		}
		if(tipo.equals("G"))
			fac.setPostFechado(true);		
		boolean eliminado=(Boolean)row.get("ELIMINADO");
		if(eliminado){
			//Proceso de cancelacion
			String userCancelacion=(String)row.get(prefix+"CANCELO");
			
			if(StringUtils.isBlank(userCancelacion))
				userCancelacion="NO DISPONIBLE";
			fac.setCancelacionDBF(true);
			String motivoCancelacion=(String)row.get(prefix+"MOTICAN");
			fac.setComentarioCancelacionDBF(motivoCancelacion);
			if(logger.isDebugEnabled()){
				logger.debug("Mapeando Venta eliminada: "+msg);
			}
		}
		Vendedor vv=ImportadorSupport.getInstance().buscarVendedor(vendedor);
		Cobrador cc=ImportadorSupport.getInstance().buscarCobrador(cobrador);
		
		fac.setVendedor(vv);
		fac.setCobrador(cc);
		if(fac.getCliente().getCredito()!=null){
			fac.setDiaDelPago(c.getCredito().getDiacobro());
			fac.setDiaRevision(c.getCredito().getDiarevision());
		}else{
			fac.setDiaDelPago(getSafaInt(row, prefix+"DIAPAGO"));
			fac.setDiaRevision(getSafaInt(row, prefix+"DIAREVI"));
		}
		if(fac.getDiaDelPago()==0)fac.setDiaDelPago(1);
		if(fac.getDiaRevision()==0)fac.setDiaRevision(1);
		RevisionDeCargosRules.instance().actualizar(fac, fecha);
		return fac;
	}

	
	
	public double getSafaDouble(Map<String, Object> row,String key){
		Number res=(Number)row.get(key);
		return res!=null?res.doubleValue():0;
	}
	
	public long getSafaLong(Map<String, Object> row,String key){
		Number res=(Number)row.get(key);
		return res!=null?res.longValue():0;
	}
	
	public int getSafaInt(Map<String, Object> row,String key){
		Number res=(Number)row.get(key);
		return res!=null?res.intValue():0;
	}	

}
